<?php
/**
 * 路由类，负责URL分发。为避免复杂，URI模式统一为PATHINFO模式
 * 
 * @author zhoujing
 */
class Router
{
	private static $singleton = null;
	private $_path = '';
	
	public static $_dir;
	public static $_control;
	public static $_action;
	public static $_param;
	
	public static function init()
	{
		if(self::$singleton == null)
		{
			self::$singleton = new Router();
		}
		
		return self::$singleton;
	}
	
	private function __construct()
	{
		Router::$_dir = false;
		Router::$_control = __Gvar::$config->get('d_control');
		Router::$_action = __Gvar::$config->get('d_action');;
		Router::$_param = array();
		
		$this->_check_route();
	}
	
	private function _get_path()
	{
		if(isset($_SERVER['PATH_INFO']))
		{
			$this->_path = str_replace(' ', '', trim($_SERVER['PATH_INFO'], '/'));
		}
		
		//过滤掉伪静态后缀名
		$pattern = "/\.".__Gvar::$config->get('url_suffix')."$/";
		$this->_path = preg_replace($pattern, '', $this->_path);
		
		if($this->_path === NULL)
		{
			$tip = "系统过滤伪静态后缀名 [ .".__Gvar::$config->get('url_suffix')." ] 时发生了错误";
			$this->route_404($tip);
		}
		
		return $this->_path;
	}
	
	private function _check_route()
	{
		//获取干净的经过简单过滤的PATHINFO信息
		$this->_get_path();
		
		//检测当前路径信息是否有路由规则
		$map = __Gvar::$config->items('router');
		foreach($map as $pattern => $replace)
		{
			$pattern = "/".$pattern."/i";
			if(preg_match($pattern, $this->_path))
			{
				$this->_path = preg_replace($pattern, $replace, $this->_path);
				break;
			}
		}
		
		//解析最终路径信息对应到相应的控制器和动作
		$this->_parse_path();
		$this->_route();
	}
	
	private function _parse_path()
	{
		$path = $this->_path;
		
		//若pathinfo信息为空，那么选取默认值
		if(!empty($path))
		{
			//分析pathinfo
			$pathinfo = explode('/', $path);
			if(is_dir(APP.'/control/'.$pathinfo[0]))
			{
				Router::$_dir = $pathinfo[0];
				array_shift($pathinfo);
			}
			//剔除出目录，余下的统一分析
			$plen = count($pathinfo);
			if($plen > 0)
			{
				Router::$_control = $pathinfo[0];
				if($plen >= 2)
				{
					Router::$_action = $pathinfo[1];
					Router::$_param = array_slice($pathinfo, 2);
				}
			}
		}
	}
	
	private function _route()
	{
		$path = APP.'/control/';
		if(Router::$_dir !== false)
		{
			$path .= Router::$_dir.'/';
		}

		if(!file_exists($path.Router::$_control.'.php'))
		{
			$msg = '控制器文件&nbsp;[&nbsp;'.$path.Router::$_control.'.php&nbsp;]&nbsp;不存在';
			$this->route_404($msg);
		}
		
		require($path.Router::$_control.'.php');
		
		if(!class_exists(Router::$_control))
		{
			$msg = '控制器文件&nbsp;[&nbsp;'.$path.Router::$_control.'.php&nbsp;]&nbsp;对应的控制器类&nbsp;[&nbsp;'.ucfirst(Router::$_control).'&nbsp;]&nbsp;不存在';
			$this->route_404($msg);
		}
		
		$control_name = Router::$_control;
		$control = new $control_name();
		
		if(!method_exists($control, Router::$_action))
		{
			$msg = '控制器类&nbsp;[&nbsp;'.ucfirst($control_name).'&nbsp;]&nbsp;中未发现方法&nbsp;[&nbsp;'.Router::$_action.'&nbsp;]&nbsp;定义';
			$this->route_404($msg);
		}
		
		call_user_func_array(array($control, Router::$_action), Router::$_param);
	}
	
	/**
	 * 友好提示的404错误
	 * 
	 * @param string $tip 错误提示，只会在开发环境或者测试环境中显示，生产环境中屏蔽
	 */
	public function route_404($tip)
	{
		if(!file_exists(APP.'/error/error_404.php'))
		{
			sys_error('系统 404 错误模板文件 [ {1} ] 不存在，请先定制模板文件！', 'error_404.php');
		}
		
		$time_limit = 15;
		if(ENV == 1 || ENV == 2)
		{
			$time_limit = 300;
		}
		
		require(APP.'/error/error_404.php');
		exit ;
	}
	
}